

#pragma once

#define __REFSTRING__

#include <string>
#include <ostream>
#include <utility>

using namespace std;

#include <boost/shared_ptr.hpp>
#include <boost/algorithm/string.hpp>


template<typename charT>
class RefString {
public:
    typedef typename std::basic_string<charT, char_traits<charT>, allocator<charT> > StdString;
public:
    typedef typename StdString::size_type size_type;
    typedef typename StdString::value_type value_type;
    typedef typename StdString::traits_type	traits_type;
    typedef typename StdString::allocator_type allocator_type;
    typedef typename StdString::difference_type difference_type;

    typedef typename StdString::pointer pointer;
    typedef typename StdString::iterator  iterator;
    typedef typename StdString::reference reference;
    typedef typename StdString::reverse_iterator reverse_iterator;

    typedef typename StdString::const_pointer const_pointer;
    typedef typename StdString::const_iterator const_iterator;
    typedef typename StdString::const_reference const_reference;
    typedef typename StdString::const_reverse_iterator const_reverse_iterator;

    static const size_type npos = size_type(-1);//StdString::npos;

public:
    explicit RefString(const allocator_type& a = allocator_type()) {
        memStr.reset(new StdString(a));
    }
    RefString(const RefString& str) {
        memStr = str.memStr;
    }
    RefString(const StdString& str) {
        memStr.reset(new StdString(str));
    }
    RefString(const RefString& str, size_type pos, size_type n = StdString::npos, const allocator_type& a = allocator_type()) {
        memStr.reset(new StdString(str.GetString(), pos, n, a));
    }
    RefString(const StdString& str, size_type pos, size_type n = StdString::npos, const allocator_type& a = allocator_type()) {
        memStr.reset(new StdString(str, pos, n, a));
    }
    RefString(const charT* s, size_type n, const allocator_type& a = allocator_type()) {
        memStr.reset(new StdString(s, n, a));
    }
    RefString(const charT* s, const allocator_type& a = allocator_type()) {
        memStr.reset(new StdString(s, a));
    }
    RefString(size_type n, charT c, const allocator_type& a = allocator_type()) {
        memStr.reset(new StdString(n, c, a));
    }
    template<class InputIterator>
    RefString(InputIterator begin, InputIterator end) {
        memStr.reset(new StdString(begin, end));
    }
public:
    virtual ~RefString(void) {}
public:
    RefString& operator= (const RefString& str) {
        memStr = str.memStr;
        return *this;
    }
    RefString& operator= (const StdString& str) {
        memStr.reset(new StdString(str));
        return *this;
    }
    RefString& operator= (const charT* s) {
        memStr.reset(new StdString(s));
        return *this;
    }
    RefString& operator= (charT c) {
        memStr.reset(new StdString(1, c));
        return *this;
    }
public:
    iterator begin() {
        return memStr->begin();
    }
    const_iterator begin() const {
        return memStr->begin();
    }
    iterator end() {
        return memStr->end();
    }
    const_iterator end() const {
        return memStr->end();
    }
    reverse_iterator rbegin() {
        return memStr->rbegin();
    }
    const_reverse_iterator rbegin() const {
        return memStr->rbegin();
    }
    reverse_iterator rend() {
        return memStr->rend();
    }
    const_reverse_iterator rend() const {
        return memStr->rend();
    }
public:
    size_type size() const {
        return memStr->size();
    }
    size_type length() const {
        return memStr->length();
    }
    size_type max_size() const {
        return memStr->max_size();
    }
    void resize(size_type n, charT c) {
        memStr->resize(n, c);
    }
    void resize(size_type n) {
        memStr->resize(n);
    }
    size_type capacity() const {
        return memStr->capacity();
    }
    void reserve(size_type res_arg = 0) {
        memStr->reserve(res_arg);
    }
    void clear() {
        memStr->clear();
    }
    bool empty() const {
        return memStr->empty();
    }
public:
    const_reference operator[](size_type pos) const {
        return memStr->operator [](pos);
    }
    reference operator[](size_type pos) {
        return memStr->operator [](pos);
    }
    const_reference at(size_type pos) const {
        return memStr->at(pos);
    }
    reference at(size_type pos) {
        return memStr->at(pos);
    }
public:
    RefString& operator+=(const RefString& str) {
        memStr->operator +=(str.GetString());
        return *this;
    }
    RefString& operator+=(const StdString& str) {
        memStr->operator +=(str);
        return *this;
    }
    RefString& operator+= (const charT* str) {
        memStr->operator +=(str);
        return *this;
    }
    RefString& operator+= (char c) {
        memStr->operator +=(c);
        return *this;
    }
    RefString& append(const RefString& str) {
        memStr->append(str.GetString());
        return *this;
    }
    RefString& append(const StdString& str) {
        memStr->append(str);
        return *this;
    }
    RefString& append(const RefString& str, size_type pos, size_type n) {
        memStr->append(str.GetString(), pos, n);
        return *this;
    }
    RefString& append(const StdString& str, size_type pos, size_type n) {
        memStr->append(str, pos, n);
        return *this;
    }
    RefString& append(const charT* s, size_type n) {
        memStr->append(s, n);
        return *this;
    }
    RefString& append(const charT* s) {
        memStr->append(s);
        return *this;
    }
    RefString& append(size_type n, charT c) {
        memStr->append(n, c);
        return *this;
    }
    template <class InputIterator>
    RefString& append(InputIterator first, InputIterator last) {
        memStr->append(first, last);
        return *this;
    }
    void push_back(charT c) {
        memStr->push_back(c);
    }

    RefString& assign(const RefString& str) {
        memStr->assign(str.GetString());
        return *this;
    }
    RefString& assign(const StdString& str) {
        memStr->assign(str);
        return *this;
    }
    RefString& assign(const RefString& str, size_type pos, size_type n) {
        memStr->assign(str.GetString(), pos, n);
        return *this;
    }
    RefString& assign(const StdString& str, size_type pos, size_type n) {
        memStr->assign(str, pos, n);
        return *this;
    }
    RefString& assign(const charT* s, size_type n) {
        memStr->assign(s, n);
        return *this;
    }
    RefString& assign(const charT* s) {
        memStr->assign(s);
        return *this;
    }
    RefString& assign(size_type n, charT c) {
        memStr->assign(n, c);
        return *this;
    }
    template <class InputIterator>
    RefString& assign(InputIterator first, InputIterator last) {
        memStr->assign(first, last);
        return *this;
    }

    RefString& insert(size_type pos1, const RefString& str) {
        memStr->insert(pos1, str.GetString());
        return *this;
    }
    RefString& insert(size_type pos1, const StdString& str) {
        memStr->insert(pos1, str);
        return *this;
    }
    RefString& insert(size_type pos1, const RefString& str, size_type pos2, size_type n) {
        memStr->insert(pos1, str.GetString(), pos2, n);
        return *this;
    }
    RefString& insert(size_type pos1, const StdString& str, size_type pos2, size_type n) {
        memStr->insert(pos1, str, pos2, n);
        return *this;
    }
    RefString& insert(size_type pos1, const charT* s, size_type n) {
        memStr->insert(pos1, s, n);
        return *this;
    }
    RefString& insert(size_type pos1, const charT* s) {
        memStr->insert(pos1, s);
        return *this;
    }
    RefString& insert(size_type pos1, size_type n, charT c) {
        memStr->insert(pos1, n, c);
        return *this;
    }
    iterator insert(iterator p, charT c) {
        return memStr->insert(p, c);
    }
    void insert(iterator p, size_type n, charT c) {
        memStr->insert(p, n, c);
    }
    template <class InputIterator>
    void insert(iterator p, InputIterator first, InputIterator last) {
        memStr->insert(p, first, last);
    }

    RefString& erase(size_type pos = 0, size_type n = RefString::npos) {
        memStr->erase(pos, n);
        return *this;
    }
    iterator erase(iterator p) {
        return memStr->erase(p);
    }
    iterator erase(iterator first, iterator last) {
        return memStr->erase(first, last);
    }

    RefString& replace(size_type pos1, size_type n1,	const RefString& str) {
        memStr->replace(pos1, n1, str.GetString());
        return *this;
    }
    RefString& replace(size_type pos1, size_type n1,	const StdString& str) {
        memStr->replace(pos1, n1, str);
        return *this;
    }
    RefString& replace(iterator i1, iterator i2,	const RefString& str) {
        memStr->replace(i1, i2, str.GetString());
        return *this;
    }
    RefString& replace(iterator i1, iterator i2,	const StdString& str) {
        memStr->replace(i1, i2, str);
        return *this;
    }
    RefString& replace(size_type pos1, size_type n1,	const RefString& str, size_type pos2, size_type n2) {
        memStr->replace(pos1, n1,  str.GetString(), pos2, n2);
        return *this;
    }
    RefString& replace(size_type pos1, size_type n1,	const StdString& str, size_type pos2, size_type n2) {
        memStr->replace(pos1, n1, str, pos2, n2);
        return *this;
    }
    RefString& replace(size_type pos1, size_type n1, const charT* s, size_type n2) {
        memStr->replace(pos1, n1, s, n2);
        return *this;
    }
    RefString& replace(iterator i1, iterator i2,	const charT* s, size_type n2) {
        memStr->replace(i1, i2, s, n2);
        return *this;
    }
    RefString& replace(size_type pos1, size_type n1,	const charT* s) {
        memStr->replace(pos1, n1, s);
        return *this;
    }
    RefString& replace(iterator i1, iterator i2,	const charT* s) {
        memStr->replace(i1, i2, s);
        return *this;
    }
    RefString& replace(size_type pos1, size_type n1,	size_type n2, charT c) {
        memStr->replace(pos1, n1, n2, c);
        return *this;
    }
    RefString& replace(iterator i1, iterator i2,	size_type n2, charT c) {
        memStr->replace(i1, i2, n2, c);
        return *this;
    }
    template <class InputIterator>
    RefString& replace(iterator i1, iterator i2,	InputIterator first, InputIterator last) {
        memStr->replace(i1, i2, first, last);
        return *this;
    }
    /*void swap ( StdString& str ){
    	memStr->swap(str);
    }*/
    void swap(RefString& str) {
        memStr->swap(str.GetString());
    }
public:
    const charT* c_str() const {
        return memStr->c_str();
    }
    charT* c_str() {
        return const_cast<charT*>(memStr->c_str());
    }
    const charT* data() const {
        return memStr->data();
    }
    charT* data() {
        return const_cast<charT*>(memStr->data());
    }
    allocator_type get_allocator() const {
        return memStr->get_allocator();
    }
    //copy to s
    size_type copy(charT* s, size_type n, size_type pos = 0) const {
        return memStr->copy(s, n, pos);
    }
    size_type find(const RefString& str, size_type pos = 0) const {
        return memStr->find(str.GetString(), pos);
    }
    size_type find(const StdString& str, size_type pos = 0) const {
        return memStr->find(str, pos);
    }
    size_type find(const charT* s, size_type pos, size_type n) const {
        return memStr->find(s, pos, n);
    }
    size_type find(const charT* s, size_type pos = 0) const {
        return memStr->find(s, pos);
    }
    size_type find(charT c, size_type pos = 0) const {
        return memStr->find(c, pos);
    }
    size_type rfind(const RefString& str, size_type pos = npos) const {
        return memStr->rfind(str.GetString(), pos);
    }
    size_type rfind(const StdString& str, size_type pos = npos) const {
        return memStr->rfind(str, pos);
    }
    size_type rfind(const charT* s, size_type pos, size_type n) const {
        return memStr->rfind(s, pos, n);
    }
    size_type rfind(const charT* s, size_type pos = npos) const {
        return memStr->rfind(s, pos);
    }
    size_type rfind(charT c, size_type pos = npos) const {
        return memStr->rfind(c, pos);
    }

    size_type find_first_of(const RefString& str, size_type pos = 0) const {
        return memStr->find_first_of(str.GetString(), pos);
    }
    size_type find_first_of(const StdString& str, size_type pos = 0) const {
        return memStr->find_first_of(str, pos);
    }
    size_type find_first_of(const charT* s, size_type pos, size_type n) const {
        return memStr->find_first_of(s, pos, n);
    }
    size_type find_first_of(const charT* s, size_type pos = 0) const {
        return memStr->find_first_of(s, pos);
    }
    size_type find_first_of(charT c, size_type pos = 0) const {
        return memStr->find_first_of(c, pos);
    }

    size_type find_last_of(const RefString& str, size_type pos = npos) const {
        return memStr->find_last_of(str.GetString(), pos);
    }
    size_type find_last_of(const StdString& str, size_type pos = npos) const {
        return memStr->find_last_of(str, pos);
    }
    size_type find_last_of(const charT* s, size_type pos,	size_type n) const {
        return memStr->find_last_of(s, pos, n);
    }
    size_type find_last_of(const charT* s, size_type pos = npos) const {
        return memStr->find_last_of(s, pos);
    }
    size_type find_last_of(charT c, size_type pos = npos) const {
        return memStr->find_last_of(c, pos);
    }

    size_type find_first_not_of(const RefString& str, size_type pos = 0) const {
        return memStr->find_first_not_of(str.GetString(), pos);
    }
    size_type find_first_not_of(const StdString& str, size_type pos = 0) const {
        return memStr->find_first_not_of(str, pos);
    }
    size_type find_first_not_of(const charT* s, size_type pos, size_type n) const {
        return memStr->find_first_not_of(s, pos, n);
    }
    size_type find_first_not_of(const charT* s, size_type pos = 0) const {
        return memStr->find_first_not_of(s, pos);
    }
    size_type find_first_not_of(charT c, size_type pos = 0) const {
        return memStr->find_first_not_of(c, pos);
    }

    size_type find_last_not_of(const RefString& str, size_type pos = npos) const {
        return memStr->find_last_not_of(str.GetString(), pos);
    }
    size_type find_last_not_of(const StdString& str, size_type pos = npos) const {
        return memStr->find_last_not_of(str, pos);
    }
    size_type find_last_not_of(const charT* s, size_type pos, size_type n) const {
        return memStr->find_last_not_of(s, pos, n);
    }
    size_type find_last_not_of(const charT* s, size_type pos = npos) const {
        return memStr->find_last_not_of(s, pos);
    }
    size_type find_last_not_of(charT c, size_type pos = npos) const {
        return memStr->find_last_not_of(c, pos);
    }

    RefString substr(size_type pos = 0, size_type n = npos) const {
        return RefString(memStr->substr(pos, n));
    }

    int compare(const RefString& str) const {
        return memStr->compare(str.GetString());
    }
    int compare(const StdString& str) const {
        return memStr->compare(str);
    }
    int compare(const charT* s) const {
        return memStr->compare(s);
    }
    int compare(size_type pos1, size_type n1,	const RefString& str) const {
        return memStr->compare(pos1, n1, str.GetString());
    }
    int compare(size_type pos1, size_type n1,	const StdString& str) const {
        return memStr->compare(pos1, n1, str);
    }
    int compare(size_type pos1, size_type n1,	const charT* s) const {
        return memStr->compare(pos1, n1, s);
    }
    int compare(size_type pos1, size_type n1,	const RefString& str, size_t pos2, size_type n2) const {
        return memStr->compare(pos1, n1, str.GetString(), pos2, n2);
    }
    int compare(size_type pos1, size_type n1,	const StdString& str, size_t pos2, size_type n2) const {
        return memStr->compare(pos1, n1, str, pos2, n2);
    }
    int compare(size_type pos1, size_type n1,	const charT* s, size_type n2) const {
        return memStr->compare(pos1, n1, s, n2);
    }
public:
    RefString Copy()const {
        return RefString(GetString());
    }
    RefString& ReplaceAll(const RefString& toDelete, const RefString& toInsert) {
        boost::algorithm::replace_all(GetString(), toDelete.GetString(), toInsert.GetString());
        return *this;
    }
    RefString ReplaceAllCopy(const RefString& toDelete, const RefString& toInsert) {
        return RefString(boost::algorithm::replace_all_copy(GetString(), toDelete.GetString(), toInsert.GetString()));
    }
    const StdString& GetString()const {
        return *(memStr.get());
    }
    StdString& GetString() {
        return *(memStr.get());
    }
private:
    boost::shared_ptr<StdString> memStr;
};


template<typename charT>  inline
void swap(RefString<charT>& left, RefString<charT>& right) {
    left.swap(right);
}

template<typename charT>  inline
basic_ostream<charT, char_traits<charT> >& operator<<(basic_ostream<charT, char_traits<charT> >& os, const RefString<charT>& s) {
    os.write(s.c_str(), s.length());
    return os;
}

//operator +
template<typename charT> inline
RefString<charT>  operator+(const RefString<charT>& _Left, const RefString<charT>& _Right) {
    RefString<charT> s = _Left.Copy();
    s += _Right;
    return s;
}
template<typename charT> inline
RefString<charT>  operator+(const RefString<charT>& _Left, const typename RefString<charT>::StdString& _Right) {
    RefString<charT> s = _Left.Copy();
    s += _Right;
    return s;
}
template<typename charT> inline
RefString<charT>  operator+(const RefString<charT>& _Left,  const charT* _Right) {
    RefString<charT> s = _Left.Copy();
    s += _Right;
    return s;
}
template<typename charT> inline
RefString<charT>  operator+(const RefString<charT>& _Left,    const charT _Right) {
    RefString<charT> s = _Left.Copy();
    s += _Right;
    return s;
}
template<typename charT> inline
RefString<charT>  operator+(const typename RefString<charT>::StdString& _Left, const RefString<charT>& _Right) {
    RefString<charT> s(_Left);
    s += _Right;
    return s;
}
template<typename charT> inline
RefString<charT>  operator+(const charT* _Left, const RefString<charT>& _Right) {
    RefString<charT> s(_Left);
    s += _Right;
    return s;
}
template<typename charT> inline
RefString<charT>  operator+(const charT _Left,    const RefString<charT>& _Right) {
    RefString<charT> s(1, _Left);
    s += _Right;
    return s;
}



//operaotr relation
//operator <
template<typename charT> inline
bool operator < (const RefString<charT>& left, const RefString<charT>& right) {
    return left.compare(right) < 0;
}
template<typename charT> inline
bool  operator<(const RefString<charT>& _Left,    const typename RefString<charT>::StdString& _Right) {
    return (_Left.compare(_Right) < 0);
}
template<typename charT> inline
bool  operator<(const RefString<charT>& _Left,    const charT* _Right) {
    return (_Left.compare(_Right) < 0);
}
template<typename charT> inline
bool  operator<(const typename RefString<charT>::StdString&  _Left,    const RefString<charT>& _Right) {
    return (_Right.compare(_Left) > 0);
}
template<typename charT> inline
bool  operator<(const charT* _Left,    const RefString<charT>& _Right) {
    return (_Right.compare(_Left) > 0);
}

//==
template<typename charT> inline
bool operator == (const RefString<charT>& left, const RefString<charT>& right) {
    return left.compare(right) == 0;
}
template<typename charT> inline
bool  operator==(const RefString<charT>& _Left,    const typename RefString<charT>::StdString& _Right) {
    return (_Left.compare(_Right) == 0);
}
template<typename charT> inline
bool  operator==(const RefString<charT>& _Left,    const charT* _Right) {
    return (_Left.compare(_Right) == 0);
}
template<typename charT> inline
bool  operator==(const typename RefString<charT>::StdString& _Left,    const RefString<charT>& _Right) {
    return (_Right.compare(_Left) == 0);
}
template<typename charT> inline
bool  operator==(const charT* _Left,    const RefString<charT>& _Right) {
    return (_Right.compare(_Left) == 0);
}

//operator !=
template<typename charT> inline
bool operator != (const RefString<charT>& _Left, const RefString<charT>& _Right) {
    return !(_Left == _Right);
}
template<typename charT> inline
bool  operator!=(const RefString<charT>& _Left,    const typename RefString<charT>::StdString& _Right) {
    return (!(_Left == _Right));
}
template<typename charT> inline
bool  operator!=(const RefString<charT>& _Left,    const charT* _Right) {
    return (!(_Left == _Right));
}
template<typename charT> inline
bool  operator!=(const typename RefString<charT>::StdString& _Left,    const RefString<charT>& _Right) {
    return (!(_Left == _Right));
}
template<typename charT> inline
bool  operator!=(const charT* _Left,    const RefString<charT>& _Right) {
    return (!(_Left == _Right));
}

//operator >
template<typename charT> inline
bool operator > (const RefString<charT>& left, const RefString<charT>& right) {
    return std::rel_ops::operator >(left, right);
}
template<typename charT> inline
bool  operator>(const RefString<charT>& _Left,    const typename RefString<charT>::StdString& _Right) {
    return (_Right < _Left);
}
template<typename charT> inline
bool  operator>(const RefString<charT>& _Left,    const charT* _Right) {
    return (_Right < _Left);
}
template<typename charT> inline
bool  operator>(const typename RefString<charT>::StdString& _Left,    const RefString<charT>& _Right) {
    return (_Right < _Left);
}
template<typename charT> inline
bool  operator>(const charT* _Left,    const RefString<charT>& _Right) {
    return (_Right < _Left);
}

//operator <=
template<typename charT> inline
bool operator <= (const RefString<charT>& _Left, const RefString<charT>& _Right) {
    return (!(_Right < _Left));
}
template<typename charT> inline
bool operator <= (const RefString<charT>& _Left, const typename RefString<charT>::StdString& _Right) {
    return (!(_Right < _Left));
}
template<typename charT> inline
bool  operator<=(const RefString<charT>& _Left,   const charT* _Right) {
    return (!(_Right < _Left));
}
template<typename charT> inline
bool  operator<=(const typename RefString<charT>::StdString& _Left,    const RefString<charT>& _Right) {
    return (!(_Right < _Left));
}
template<typename charT> inline
bool  operator<=(const charT* _Left,    const RefString<charT>& _Right) {
    return (!(_Right < _Left));
}

//operator >=
template<typename charT> inline
bool operator >= (const RefString<charT>& _Left, const RefString<charT>& _Right) {
    return (!(_Left < _Right));
}
template<typename charT> inline
bool operator >= (const RefString<charT>& _Left, const typename RefString<charT>::StdString& _Right) {
    return (!(_Left < _Right));
}
template<typename charT> inline
bool  operator>=(const RefString<charT>& _Left,    const charT* _Right) {
    return (!(_Left < _Right));
}
template<typename charT> inline
bool  operator>=(const typename RefString<charT>::StdString& _Left,    const RefString<charT>& _Right) {
    return (!(_Left < _Right));
}
template<typename charT> inline
bool  operator>=(const charT* _Left,    const RefString<charT>& _Right) {
    return (!(_Left < _Right));
}

